<template>
  <div class="action-editor">
    <div class="editor-container">
      <div 
        ref="editorRef"
        class="code-editor"
        contenteditable="true"
        @input="handleInput"
        @keydown="handleKeydown"
        @paste="handlePaste"
        spellcheck="false"
        autocomplete="off"
        autocorrect="off"
        autocapitalize="off"
        data-gramm="false"
        data-gramm_editor="false"
        data-enable-grammarly="false"
      ></div>
    </div>
    

  </div>
</template>

<script setup lang="ts">
import { ref, watch, nextTick, onMounted } from 'vue';

interface Props {
  value: string;
}

interface Emits {
  (e: 'update:value', value: string): void;
}

interface HistoryState {
  content: string;
  cursorPosition: number;
}

const props = defineProps<Props>();
const emit = defineEmits<Emits>();

// 组件状态
const editorRef = ref<HTMLElement>();
const currentCode = ref('');

// 撤销重做历史记录
const history = ref<HistoryState[]>([]);
const historyIndex = ref(-1);
const isApplyingHistory = ref(false);

// 语法高亮相关状态
const highlightTimeout = ref<any>(null);
const lastHighlightedText = ref('');

// JavaScript关键字和内置对象
const jsKeywords = [
  'function', 'var', 'let', 'const', 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'default',
  'break', 'continue', 'return', 'try', 'catch', 'finally', 'throw', 'new', 'this', 'typeof', 'instanceof'
];

const builtinObjects = [
  'console', 'JSON', 'Math', 'Date', 'Array', 'Object', 'String', 'Number', 'Boolean', 'RegExp'
];

const customObjects = ['req', 'resp', 'nf'];

// 保存历史状态
const saveToHistory = (content: string, cursorPosition: number) => {
  if (isApplyingHistory.value) return;
  
  // 如果当前状态与历史记录中的最后一个状态相同，则不保存
  const lastState = history.value[historyIndex.value];
  if (lastState && lastState.content === content) return;
  
  // 删除当前索引之后的所有历史记录
  history.value = history.value.slice(0, historyIndex.value + 1);
  
  // 添加新的历史状态
  history.value.push({ content, cursorPosition });
  historyIndex.value = history.value.length - 1;
  
  // 限制历史记录数量
  if (history.value.length > 50) {
    history.value.shift();
    historyIndex.value--;
  }
};

// 撤销操作
const undo = () => {
  if (historyIndex.value > 0) {
    historyIndex.value--;
    applyHistoryState(history.value[historyIndex.value]);
  }
};

// 重做操作
const redo = () => {
  if (historyIndex.value < history.value.length - 1) {
    historyIndex.value++;
    applyHistoryState(history.value[historyIndex.value]);
  }
};

// 应用历史状态
const applyHistoryState = (state: HistoryState) => {
  if (!editorRef.value) return;
  
  isApplyingHistory.value = true;
  
  // 更新内容
  currentCode.value = state.content;
  editorRef.value.textContent = state.content;
  
  // 应用语法高亮
  applySyntaxHighlighting();
  
  // 恢复光标位置
  nextTick(() => {
    setCursorPosition(state.cursorPosition);
    emit('update:value', state.content);
    isApplyingHistory.value = false;
  });
};

// 获取光标位置
const getCursorPosition = (): number => {
  const selection = window.getSelection();
  if (!selection || selection.rangeCount === 0) return 0;
  
  const range = selection.getRangeAt(0);
  const preCaretRange = range.cloneRange();
  preCaretRange.selectNodeContents(editorRef.value!);
  preCaretRange.setEnd(range.endContainer, range.endOffset);
  
  return preCaretRange.toString().length;
};

// 设置光标位置
const setCursorPosition = (position: number) => {
  if (!editorRef.value) return;
  
  const selection = window.getSelection();
  if (!selection) return;
  
  const walker = document.createTreeWalker(
    editorRef.value,
    NodeFilter.SHOW_TEXT,
    null
  );
  
  let currentPosition = 0;
  let node;
  
  while (node = walker.nextNode()) {
    const textNode = node as Text;
    const textLength = textNode.textContent?.length || 0;
    
    if (currentPosition + textLength >= position) {
      const range = document.createRange();
      range.setStart(textNode, position - currentPosition);
      range.setEnd(textNode, position - currentPosition);
      selection.removeAllRanges();
      selection.addRange(range);
      return;
    }
    
    currentPosition += textLength;
  }
};

// 处理输入
const handleInput = (event: Event) => {
  const target = event.target as HTMLElement;
  const text = target.textContent || '';
  const cursorPosition = getCursorPosition();
  
  currentCode.value = text;
  emit('update:value', text);
  
  // 保存到历史记录
  saveToHistory(text, cursorPosition);
  
  // 延迟应用语法高亮，避免影响输入，并添加防抖
  clearTimeout(highlightTimeout.value);
  highlightTimeout.value = setTimeout(() => {
    // 只有当内容真正不同时才跳过高亮
    if (text !== lastHighlightedText.value) {
      applySyntaxHighlighting();
      lastHighlightedText.value = text;
    }
  }, 200); // 减少延迟到200ms，提高响应性
};

// 处理粘贴
const handlePaste = (event: ClipboardEvent) => {
  event.preventDefault();
  
  const text = event.clipboardData?.getData('text/plain') || '';
  insertText(text);
};

// 处理键盘按下事件
const handleKeydown = (event: KeyboardEvent) => {
  const key = event.key;
  const ctrlKey = event.ctrlKey || event.metaKey;
  
  // Ctrl+Z 撤销
  if (ctrlKey && key === 'z' && !event.shiftKey) {
    event.preventDefault();
    undo();
    return;
  }
  
  // Ctrl+Shift+Z 重做
  if (ctrlKey && key === 'Z' && event.shiftKey) {
    event.preventDefault();
    redo();
    return;
  }
  
  // Ctrl+Y 重做（Windows风格）
  if (ctrlKey && key === 'y') {
    event.preventDefault();
    redo();
    return;
  }
  
  // Tab键插入空格
  if (key === 'Tab') {
    event.preventDefault();
    insertText('  '); // 插入2个空格
    return;
  }
  
  // Enter键自动缩进
  if (key === 'Enter') {
    event.preventDefault();
    const selection = window.getSelection();
    if (selection && selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      const beforeCursor = range.startContainer.textContent?.substring(0, range.startOffset) || '';
      const lines = (editorRef.value?.textContent || '').split('\n');
      const currentLineIndex = beforeCursor.split('\n').length - 1;
      const currentLine = lines[currentLineIndex] || '';
      const indent = currentLine.match(/^(\s*)/)?.[1] || '';
      
      // 如果当前行以{结尾，增加缩进
      let newIndent = indent;
      if (currentLine.trim().endsWith('{')) {
        newIndent += '  ';
      }
      
      insertText('\n' + newIndent);
    }
    return;
  }
  
  // 移除自动配对括号功能，因为它会干扰用户输入
  // 注释掉以下代码以禁用自动补全
  /*
  // 自动配对括号
  const pairs: Record<string, string> = {
    '(': ')',
    '[': ']',
    '{': '}',
    '"': '"',
    "'": "'"
  };
  
  if (pairs[key]) {
    event.preventDefault();
    const closingChar = pairs[key];
    insertText(key + closingChar);
    
    // 将光标移到括号中间
    const selection = window.getSelection();
    if (selection && selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      range.setStart(range.startContainer, range.startOffset - 1);
      range.setEnd(range.startContainer, range.startOffset - 1);
      selection.removeAllRanges();
      selection.addRange(range);
    }
    return;
  }
  */
};

// 插入文本
const insertText = (text: string) => {
  const selection = window.getSelection();
  if (selection && selection.rangeCount > 0) {
    const range = selection.getRangeAt(0);
    range.deleteContents();
    const textNode = document.createTextNode(text);
    range.insertNode(textNode);
    range.setStartAfter(textNode);
    range.setEndAfter(textNode);
    selection.removeAllRanges();
    selection.addRange(range);
    
    // 触发input事件
    const event = new Event('input', { bubbles: true });
    editorRef.value?.dispatchEvent(event);
  }
};

// 应用语法高亮
const applySyntaxHighlighting = () => {
  if (!editorRef.value || isApplyingHistory.value) return;
  
  // 获取纯文本内容，避免处理已经包含HTML标签的内容
  const text = editorRef.value.textContent || '';
  const cursorPosition = getCursorPosition();
  
  // 生成高亮HTML
  const highlightedHTML = highlightJavaScript(text);
  
  // 更新HTML内容
  editorRef.value.innerHTML = highlightedHTML;
  
  // 恢复光标位置
  nextTick(() => {
    setCursorPosition(cursorPosition);
  });
};

// JavaScript语法高亮
const highlightJavaScript = (code: string): string => {
  // 先转义HTML字符
  let highlighted = escapeHtml(code);
  
  // 按顺序应用语法高亮，避免冲突
  
  // 1. 高亮字符串（先处理字符串，避免字符串内的关键字被高亮）
  highlighted = highlighted.replace(
    /"([^"\\]|\\.)*"/g,
    '<span class="string">$&</span>'
  );
  
  highlighted = highlighted.replace(
    /'([^'\\]|\\.)*'/g,
    '<span class="string">$&</span>'
  );
  
  // 2. 高亮注释（在字符串之后，避免字符串内的注释符号被处理）
  highlighted = highlighted.replace(
    /\/\/.*$/gm,
    '<span class="comment">$&</span>'
  );
  
  highlighted = highlighted.replace(
    /\/\*[\s\S]*?\*\//g,
    '<span class="comment">$&</span>'
  );
  
  // 3. 高亮数字
  highlighted = highlighted.replace(
    /\b\d+(\.\d+)?\b/g,
    (match) => {
      // 检查是否已经在span标签内
      return `<span class="number">${match}</span>`;
    }
  );
  
  // 4. 高亮关键字（避免已经被标签包围的内容）
  jsKeywords.forEach(keyword => {
    const regex = new RegExp(`\\b${keyword}\\b`, 'g');
    highlighted = highlighted.replace(regex, (match, offset, string) => {
      // 简单检查是否在HTML标签内
      const beforeMatch = string.substring(0, offset);
      const lastOpenTag = beforeMatch.lastIndexOf('<');
      const lastCloseTag = beforeMatch.lastIndexOf('>');
      
      // 如果最近的是开标签，说明在标签内，不处理
      if (lastOpenTag > lastCloseTag) {
        return match;
      }
      
      return `<span class="keyword">${match}</span>`;
    });
  });
  
  // 5. 高亮内置对象
  builtinObjects.forEach(obj => {
    const regex = new RegExp(`\\b${obj}\\b`, 'g');
    highlighted = highlighted.replace(regex, (match, offset, string) => {
      const beforeMatch = string.substring(0, offset);
      const lastOpenTag = beforeMatch.lastIndexOf('<');
      const lastCloseTag = beforeMatch.lastIndexOf('>');
      
      if (lastOpenTag > lastCloseTag) {
        return match;
      }
      
      return `<span class="builtin">${match}</span>`;
    });
  });
  
  // 6. 高亮自定义对象
  customObjects.forEach(obj => {
    const regex = new RegExp(`\\b${obj}\\b`, 'g');
    highlighted = highlighted.replace(regex, (match, offset, string) => {
      const beforeMatch = string.substring(0, offset);
      const lastOpenTag = beforeMatch.lastIndexOf('<');
      const lastCloseTag = beforeMatch.lastIndexOf('>');
      
      if (lastOpenTag > lastCloseTag) {
        return match;
      }
      
      return `<span class="custom">${match}</span>`;
    });
  });
  
  // 7. 高亮函数调用
  highlighted = highlighted.replace(
    /(\w+)(\s*\()/g,
    (match, funcName, paren, offset, string) => {
      const beforeMatch = string.substring(0, offset);
      const lastOpenTag = beforeMatch.lastIndexOf('<');
      const lastCloseTag = beforeMatch.lastIndexOf('>');
      
      if (lastOpenTag > lastCloseTag) {
        return match;
      }
      
      return `<span class="function">${funcName}</span>${paren}`;
    }
  );
  
  return highlighted;
};

// 转义HTML字符
const escapeHtml = (text: string): string => {
  const div = document.createElement('div');
  div.textContent = text;
  return div.innerHTML;
};

// 初始化编辑器
const initializeEditor = () => {
  if (!editorRef.value) return;
  
  const initialContent = props.value || 'function main(req, resp, nf) {\n  // 在这里编写规则行为代码\n}';
  editorRef.value.textContent = initialContent;
  currentCode.value = initialContent;
  
  // 保存初始状态到历史记录
  saveToHistory(initialContent, 0);
  
  // 应用语法高亮
  applySyntaxHighlighting();
  lastHighlightedText.value = initialContent; // 更新高亮文本记录
  
  // 设置光标到函数体内
  nextTick(() => {
    const functionBodyPosition = initialContent.indexOf('// 在这里编写规则行为代码');
    if (functionBodyPosition !== -1) {
      setCursorPosition(functionBodyPosition);
    }
  });
};

// 监听props变化
watch(() => props.value, (newValue) => {
  if (newValue !== currentCode.value && !isApplyingHistory.value) {
    currentCode.value = newValue;
    if (editorRef.value) {
      editorRef.value.textContent = newValue;
      applySyntaxHighlighting();
      lastHighlightedText.value = newValue; // 更新高亮文本记录
    }
  }
});

// 组件挂载后初始化
onMounted(() => {
  if (editorRef.value) {
    initializeEditor();
  }
});

// 监听editorRef变化
watch(editorRef, (el) => {
  if (el) {
    initializeEditor();
  }
});
</script>

<style scoped>
.action-editor {
  width: 100%;
  height: 100%;
}

.editor-container {
  position: relative;
  height: 100%;
}

.code-editor {
  width: 100%;
  height: 100%;
  min-height: 300px;
  padding: 16px;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  background: #1e1e1e;
  color: #d4d4d4;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
  white-space: pre;
  overflow: auto;
  outline: none;
  transition: border-color 0.3s;
  resize: none;
}

.code-editor:focus {
  border-color: var(--primary-color);
}



/* 语法高亮样式 */
:deep(.keyword) {
  color: #569cd6;
  font-weight: bold;
}

:deep(.string) {
  color: #ce9178;
}

:deep(.number) {
  color: #b5cea8;
}

:deep(.comment) {
  color: #6a9955;
  font-style: italic;
}

:deep(.builtin) {
  color: #4ec9b0;
}

:deep(.custom) {
  color: #9cdcfe;
  font-weight: bold;
}

:deep(.function) {
  color: #dcdcaa;
}

/* 滚动条样式 */
.code-editor::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.code-editor::-webkit-scrollbar-track {
  background: #2d2d30;
}

.code-editor::-webkit-scrollbar-thumb {
  background: #424245;
  border-radius: 4px;
}

.code-editor::-webkit-scrollbar-thumb:hover {
  background: #4f4f52;
}
</style> 